package com.wh.wisdomsite.xbox.utils.encrypt.aes;

import com.wh.wisdomsite.xbox.utils.random.RandomTool;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.crypto.*;
import javax.crypto.spec.*;


/**
 * AES加密解密工具1
 * @Package com.wh.wisdomsite.xbox.utils.encrypt.aes
 * @author 谢泽鹏
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2014
 * @version V1.0
 */
public class AesTool {

    private static final Log logger = LogFactory.getLog(AesTool.class);

    /**
     * AES加密
     * @param sSrc 加密源
     * @param sKey 加密key(可以用16个字母和数字组成)
     * @return 加密后的字符串
     * */
 	public static String Encrypt(String sSrc, String sKey) {
        //加密后文本
        String encrypt_src = null;
        try {
            //判断sKey是否正确
            if (null == sKey) {
                logger.error("Encrypt->>加密sKey为空");
                return null;
            }
            //判断sKey是否为16位
            if (16 != sKey.length()) {
                logger.error("Encrypt->>加密sKey错误");
                return null;
            }
            //判断sSrc不为空
            if (null == sSrc) {
                logger.error("Encrypt->>加密sSrc为空");
                return null;
            }
            logger.info("Encrypt->>加密源sSrc：" + sSrc);
            logger.info("Encrypt->>加密sKey：" + sKey);
            byte[] raw = sKey.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes());
            encrypt_src =byte2hex(encrypted).toLowerCase();
            logger.info("Encrypt->>加密值：" + encrypt_src);
        } catch (Exception e){
            e.printStackTrace();
            encrypt_src = null;
            logger.error("Encrypt->>加密Exception：" + e.getMessage());
        }
		    return encrypt_src;
	}

    /**
     * AES解密
     * @param sSrc 解密源
     * @param sKey 解密key(可以用16个字母和数字组成)
     * @return 解密后的字符串
     * */
    public static String Decrypt(String sSrc, String sKey) {
        //解密后文本
        String decrypt_src = null;
        try {
            //判断sKey是否正确
            if (null == sKey) {
                logger.error("Decrypt->>加密sKey为空");
                return null;
            }
            //判断sKey是否为16位
            if (16 != sKey.length()) {
                logger.error("Decrypt->>加密sKey错误");
                return null;
            }
            //判断sSrc不为空
            if (null == sSrc) {
                logger.error("Encrypt->>加密sSrc为空");
                return null;
            }
            logger.info("Decrypt->>解密源sSrc：" + sSrc);
            logger.info("Decrypt->>解密sKey：" + sKey);
            byte[] raw = sKey.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] encrypted1 = hex2byte(sSrc);
            byte[] original = cipher.doFinal(encrypted1);
            decrypt_src = new String(original);
            logger.info("Decrypt->>解密值：" + decrypt_src);
        } catch (Exception e) {
            e.printStackTrace();
            decrypt_src = null;
            logger.error("Decrypt->>解密Exception：" + e.getMessage());
        }
            return decrypt_src;
    }


	
	/**
	 * 将16进制字符串转换为byte
	 * @param str 操作的16进制字符串
	 * @return byte[] 
	 * */
	public static byte[] hex2byte(String str) {
		if (str == null) {
			return null;
		}
		int length = str.length();
		if (length % 2 == 1) {
			return null;
		}
		byte[] b = new byte[length / 2];
		for (int i = 0; i != length / 2; i++) {
			b[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2),16);
		}
		return b;
	}


	/**
	 * 将byte[]转换为16进制字符串
	 * @param b 要操作的16进制字符串
	 * @return byte[]
	 * */
	public static String byte2hex(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			stmp = (Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1) {
				hs = hs + "0" + stmp;
			} else {
				hs = hs + stmp;
			}
		}
		return hs.toUpperCase();
	}

    /*
     * 加密用的Key 可以用16个字母和数字组成，最好不要用保留字符，虽然不会错，至于怎么裁决，个人看情况而定
     */
    public static void main(String[] args) throws Exception {
        System.out.println("############加减密第1测试开始###########");
        String cKey = RandomTool.getNumberLetterAll(16);


        String cSrc = "c01932caa3944d3b8735a3cb8462f2d9";
        long lStart = System.currentTimeMillis();
        String enString = AesTool.Encrypt(cSrc, cKey);
        long lUseTime = System.currentTimeMillis() - lStart;
        System.out.println("加密值：" + enString);
        System.out.println("加密耗时：" + lUseTime + "毫秒");

        lStart = System.currentTimeMillis();
        String deString = AesTool.Decrypt(enString, cKey);
        lUseTime = System.currentTimeMillis() - lStart;
        System.out.println("解密值：" + deString);
        System.out.println("解密耗时：" + lUseTime + "毫秒");
        System.out.println("############加减密第1测试结束###########");
    }


}
